package com.ls.utils;


import com.ls.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;

import static com.ls.utils.DateTimeUtil.DEFAULT_FORMAT_DATE;

/**
 * AES工具类
 *
 * @author Javin - pengyu
 * @date 2020/06/24
 * 1 设计5G
 */
@Slf4j
public class Aes5GUtil {

    private static final String KEY_ALGORITHM = "AES";

    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/NOPadding";

    private static final String PHONE_PASSWORD = "hyw9P8sW";

    private static final String CLIENT_ID = "web-app-sxt";

    private static final String KEY = "0pGyOTvE7uVpnSQ8";

    private static final String OFFSET = "snjgrHJlmaj5TsEt";

//    private static final String PREFIX_INDEX = "https://merchant.test.imas.vpclub.cn/#/login?data=";
    private static final String PREFIX_INDEX = "https://merchant.frontend.imas.vpclub.cn/#/login?data=";
//    private static final String PREFIX_LOGOUT ="https://imas.tsbe.vpclub.cn/api/open-api/v1/login/loginOut?data=";
    private static final String PREFIX_LOGOUT ="https://service.imas.vpclub.cn/api/open-api/v1/login/loginOut?data=";

    /**
     * des解密
     *
     * @param data data
     * @param pass pass
     * @return String
     * @author Javin
     * @date 2020/06/24
     */
    public static String decryptAES(String data, String pass) throws Exception {
        Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(pass.getBytes(), KEY_ALGORITHM), new IvParameterSpec(pass.getBytes()));
        byte[] result = cipher.doFinal(Base64.decode(data.getBytes(StandardCharsets.UTF_8)));
        return new String(result, StandardCharsets.UTF_8);
    }

    //加密
    public static String encryptAES(String data, String key) {
        String ivString = key;
        //偏移量
        byte[] iv = ivString.getBytes();
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int length = dataBytes.length;
            //计算需填充长度
            if (length % blockSize != 0) {
                length = length + (blockSize - (length % blockSize));
            }
            byte[] plaintext = new byte[length];
            //填充
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            //设置偏移量参数
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] b = cipher.doFinal(plaintext);
            return org.apache.commons.codec.binary.Base64.encodeBase64String(b);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解密方式： AES128(CBC/PKCS5Padding) + Base64
    public static String decrypt(String textDeCipher, String keySpec, String offset) throws Exception {
        byte[] byteArray = org.apache.commons.codec.binary.Base64.decodeBase64(textDeCipher);   //先用Base64解码
        IvParameterSpec ivSpec = new IvParameterSpec(offset.getBytes());
        Key key = new SecretKeySpec(keySpec.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);     //与加密时不同MODE:Cipher.DECRYPT_MODE
        byte[] ret = cipher.doFinal(byteArray);
        String rawText = new String(ret, "utf-8");
        System.out.println("rawText=" + rawText);
        return rawText;
    }

    //加密方式： AES128(CBC/PKCS5Padding) + Base64
    public static String encrypt(String encryInfo, String key, String offset) throws Exception {
        Key keySpec = new SecretKeySpec(key.getBytes(), "AES");    //两个参数，第一个为私钥字节数组， 第二个为加密方式 AES或者DES
        IvParameterSpec ivSpec = new IvParameterSpec(offset.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");    //实例化加密类，参数为加密方式，要写全
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); //初始化，此方法可以采用三种方式，按服务器要求来添加。（1）无第三个参数（2）第三个参数为SecureRandom random = new SecureRandom();中random对象，随机数。(AES不可采用这种方法)（3）采用此代码中的IVParameterSpec
        byte[] b = cipher.doFinal(encryInfo.getBytes());        //加密操作,返回加密后的字节数组，然后需要编码。主要编解码方式有Base64, HEX, UUE, 7bit等等。此处看服务器需要什么编码方式
        String encryptText = org.apache.commons.codec.binary.Base64.encodeBase64String(b);     //Base64、HEX等编解码
        encryptText = URLEncoder.encode(encryptText, "utf-8");
        System.out.println("encryptText=" + encryptText);
        log.info("encryptText=" + encryptText);
        return encryptText;
    }
    /** 获取登录主页的url */
    public static String getURL(String phone) throws Exception {
        String operateTime = DateTimeUtil.formatDateToString(new Date(), DEFAULT_FORMAT_DATE);
        StringBuilder encryInfoSb = new StringBuilder("{\"merchantId\":\""+ phone +"\",\"passwd\":\""+ PHONE_PASSWORD +"\",\"operateTime\":\""+ operateTime+"\",\"clientId\":\""+CLIENT_ID+"\"}");
        return PREFIX_INDEX + encrypt(encryInfoSb.toString() ,KEY ,OFFSET);
    }
    /** 登出 */
    public static ResultData logOut(String phone) throws Exception {
        String operateTime = DateTimeUtil.formatDateToString(new Date(), DEFAULT_FORMAT_DATE);
        StringBuilder encryInfoSb = new StringBuilder("{\"merchantId\":\""+ phone +"\",\"passwd\":\""+ PHONE_PASSWORD +"\",\"operateTime\":\""+ operateTime+"\",\"clientId\":\""+CLIENT_ID+"\"}");
        String resultStr =  HttpUtils.sendPost(PREFIX_LOGOUT + encrypt(encryInfoSb.toString() ,KEY ,OFFSET));
        log.info("5G logOut resultStr=" + resultStr);
        if(StringUtils.isNotBlank(resultStr)){
            return ResultData.convertFromStr(resultStr);
        }else{
            return ResultData.failure("5G logOut fail null return");
        }
    }

}

